/*
 * Copyright (C) 2010 Fores Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.fores.midori.core.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

/**
 * 独自のクラスローダーも扱えるようにしたObjectInputStreamクラス。<br>
 * クラスローダーを指定しない場合は、通常のObjectInputStreamクラスとして動作します。<br>
 * (このクラスのスレッドセーフ性はObjectInputStreamクラスと同様です。)<br>
 */
public class CustomClassLoaderObjectInputStream extends ObjectInputStream {
	//==========================================================
	//フィールド

	/**
	 * クラスローダー
	 */
	protected final ClassLoader classLoader;


	//==========================================================
	//メソッド

	//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	//コンストラクタ

	/**
	 * コンストラクタです。<br>
	 * 
	 * @param is 入力ストリーム
	 * @param classLoader クラスローダー
	 * @throws IOException 入出力エラーが発生した場合
	 */
	public CustomClassLoaderObjectInputStream(InputStream is,
			ClassLoader classLoader) throws IOException {
		//親クラスのコンストラクタの呼び出し
		super(is);


		//==========================================================
		//引数の値をフィールドに設定

		//クラスローダー
		this.classLoader = classLoader;
	}


	//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	//オーバーライドするメソッド

	/**
	 * 指定されたストリームクラスの記述に対応するクラスをロードします。<br>
	 * コンストラクタでクラスローダーが指定されている場合は、そのクラスローダーを使ってロードします。<br>
	 * 
	 * @param desc ObjectStreamClass クラスのインスタンス 
	 * @return desc に対応する Class オブジェクト 
	 * @throws IOException 通常の入出力関連の例外が発生した場合 
	 * @throws ClassNotFoundException 直列化されたオブジェクトのクラスが見つからなかった場合
	 */
	@Override
	protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,
			ClassNotFoundException {
		//フィールドのクラスローダーがnullの場合
		if (this.classLoader == null) {
			//親クラスの処理を呼び出す
			return super.resolveClass(desc);
		}
		//それ以外の場合
		//(クラスローダーが指定されている場合)
		else {
			try {
				//フィールドのクラスローダーを使ってクラス情報をロードした結果を返す
				return this.classLoader.loadClass(desc.getName());
			}
			//例外が発生した場合
			catch (Exception e) {
				//親クラスの処理を呼び出す
				return super.resolveClass(desc);
			}
		}
	}
}
